﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace Redbrick.Silverlight.UI
{

    public class DoubleClickArgs : EventArgs
    {
        public DoubleClickArgs(MouseEventArgs meArgs)
        {
            this.MouseEventArgs = meArgs;
        }

        public MouseEventArgs MouseEventArgs { get; private set; }
    }

    public class DoubleClick
    {

        #region Consts & Settings



        #endregion Consts & Settings

        #region Declarations
        private static Dictionary<UIElement, DoubleClick> Handlers = new Dictionary<UIElement, DoubleClick>();

        public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(DoubleClick),
                                                                                                            new PropertyMetadata(null,OnCommandChanged));

        private UIElement _attached = null;
        private Delegate _handler = null;
        private ICommand _command = null;
        private DateTime _lastClick = DateTime.Now;
        private bool _firstClick = false;
        private Point _clickPosition = new Point();

        #endregion Declarations

        #region Constructor

        private DoubleClick(UIElement el)
        {
            this.Attach(el);
        }

        #endregion Constructor

        #region Methods

        public void Attach(UIElement el)
        {
            if (el is FrameworkElement)
                ((FrameworkElement)el).Unloaded += DoubleClick_Unloaded;
            this._attached = el;
            _handler = new MouseButtonEventHandler(this.ClickHandler);
            el.AddHandler(UIElement.MouseLeftButtonUpEvent, _handler, true);
        }
        void DoubleClick_Unloaded(object sender, RoutedEventArgs e)
        {
            Detach(sender as UIElement);
        }
        public void Detach(UIElement el)
        {
            if (el is FrameworkElement)
                ((FrameworkElement)el).Unloaded -= DoubleClick_Unloaded;

            el.RemoveHandler(UIElement.MouseLeftButtonUpEvent, _handler);
        }


        private void ClickHandler(object sender, MouseEventArgs args)
        {
            UIElement element = sender as UIElement;
            DateTime clickTime = DateTime.Now;

            TimeSpan span = clickTime - _lastClick;

            if (span.TotalMilliseconds > 300 || _firstClick == false)
            {
                _clickPosition = args.GetPosition(element);
                _firstClick = true;
                _lastClick = DateTime.Now;
            }
            else
            {
                Point position = args.GetPosition(element);
                if (Math.Abs(_clickPosition.X - position.X) < 4 &&
                    Math.Abs(_clickPosition.Y - position.Y) < 4)
                {
                    this.RaiseDoubleClick(args);
                }
                _firstClick = false;
            }
        }

        private void RaiseDoubleClick(MouseEventArgs args)
        {
            if (this._command != null && _command.CanExecute(args))
                _command.Execute(args);

        }

        /// <summary>
        /// Handles changes to the Command property.
        /// </summary>
        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is UIElement)
            {
                UIElement b = d as UIElement;
                ICommand c = e.NewValue as ICommand;
                DoubleClick dc = null;
                if (!Handlers.ContainsKey(b))
                {
                    Handlers.Add(b, new DoubleClick(b));
                }

                dc = Handlers[b];
                dc._command = c;
                dc.Detach(b);
                dc.Attach(b);
            }
        }


        public static void SetCommand(UIElement element, ICommand value)
        {
            element.SetValue(DoubleClick.CommandProperty, value);
        }
        public static ICommand GetCommand(UIElement element)
        {
            return (ICommand)element.GetValue(DoubleClick.CommandProperty);
        }

        #endregion Methods

        #region Events

        //public event EventHandler<DoubleClickArgs> OnLeftMouseDoubleClick;

        #endregion Events

        #region Properties


        #endregion Properties

    }
}
